home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / hplip / makecopies.py < prev    next >
Text File  |  2008-10-13  |  14KB  |  448 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Author: Don Welch
  21. #
  22.  
  23. __version__ = '3.3'
  24. __title__ = "Make Copies Utility"
  25. __doc__ = "PC initiated make copies on supported HP AiO and MFP devices."
  26.  
  27. # Std Lib
  28. import sys
  29. import os
  30. import getopt
  31. import re
  32. import Queue
  33. import time
  34. import operator
  35.  
  36. # Local
  37. from base.g import *
  38. from base import utils, device, pml, tui
  39. from copier import copier
  40. from prnt import cups
  41.  
  42.  
  43. log.set_module('hp-makecopies')
  44.  
  45. USAGE = [(__doc__, "", "name", True),
  46.          ("Usage: hp-makecopies [PRINTER|DEVICE-URI] [MODE] [OPTIONS]", "", "summary", True),
  47.          utils.USAGE_ARGS,
  48.          utils.USAGE_DEVICE,
  49.          ("To specify a CUPS printer:", "-P<printer>, -p<printer> or --printer=<printer>", "option", False),
  50.          utils.USAGE_SPACE,
  51.          ("[MODE]", "", "header", False),
  52.          ("Enter graphical UI mode:", "-u or --gui (Default)", "option", False),
  53.          ("Run in non-interactive mode (batch mode):", "-n or --non-interactive", "option", False),
  54.          utils.USAGE_SPACE,
  55.          utils.USAGE_OPTIONS,
  56.          ("Number of copies:", "-m<num_copies> or --copies=<num_copies> or --num=<num_copies> (1-99)", "option", False),
  57.          ("Reduction/enlargement:", "-r<%> or --reduction=<%> or --enlargement=<%> (25-400%)", "option", False),
  58.          ("Quality:", "-q<quality> or --quality=<quality> (where quality is: 'fast', 'draft', 'normal', 'presentation', or 'best')", "option", False),
  59.          ("Contrast:", "-c<contrast> or --contrast=<contrast> (-5 to +5)", "option", False),
  60.          ("Fit to page (flatbed only):", "-f or --fittopage or --fit (overrides reduction/enlargement)", "option", False),
  61.          utils.USAGE_LANGUAGE2,
  62.          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2, utils.USAGE_LOGGING3,
  63.          utils.USAGE_HELP,
  64.          utils.USAGE_SPACE,
  65.          utils.USAGE_NOTES,
  66.          utils.USAGE_STD_NOTES1, utils.USAGE_STD_NOTES2, 
  67.          ("3. If any copy parameter is not specified (contrast, reduction, etc), the default values from the device are used.", "", "note", False),
  68.          ]
  69.  
  70.  
  71. def usage(typ='text'):
  72.     if typ == 'text':
  73.         utils.log_title(__title__, __version__)
  74.  
  75.     utils.format_text(USAGE, typ, __title__, 'hp-makecopies', __version__)
  76.     sys.exit(0)
  77.  
  78.  
  79. try:
  80.     opts, args = getopt.getopt(sys.argv[1:], 'P:p:d:hl:gm:c:q:r:funb:',
  81.                                ['printer=', 'device=', 'help', 'logging=',
  82.                                 'num=', 'copies=', 'contrast=', 'quality=',
  83.                                 'reduction=', 'enlargement=', 'fittopage', 
  84.                                 'fit', 'gui', 'help-rest', 'help-man',
  85.                                 'help-desc', 'non-interactive', 'bus=', 
  86.                                 'lang='])
  87. except getopt.GetoptError, e:
  88.     log.error(e.msg)
  89.     usage()
  90.  
  91. printer_name = None
  92. device_uri = None
  93. log_level = logger.DEFAULT_LOG_LEVEL
  94. bus = ['cups']
  95. num_copies = None
  96. reduction = None
  97. reduction_spec = False
  98. contrast = None
  99. quality = None
  100. fit_to_page = None
  101. mode = GUI_MODE
  102. mode_specified = False
  103. loc = None
  104.  
  105. if os.getenv("HPLIP_DEBUG"):
  106.     log.set_level('debug')
  107.  
  108. for o, a in opts:
  109.     if o in ('-h', '--help'):
  110.         usage()
  111.  
  112.     elif o == '--help-rest':
  113.         usage('rest')
  114.  
  115.     elif o == '--help-man':
  116.         usage('man')
  117.  
  118.     elif o == '--help-desc':
  119.         print __doc__,
  120.         sys.exit(0)
  121.  
  122.     elif o in ('-p', '-P', '--printer'):
  123.         if a.startswith('*'):
  124.             printer_name = cups.getDefaultPrinter()
  125.             log.debug(printer_name)
  126.             
  127.             if printer_name is not None:
  128.                 log.info("Using CUPS default printer: %s" % printer_name)
  129.             else:
  130.                 log.error("CUPS default printer is not set.")
  131.             
  132.         else:
  133.             printer_name = a
  134.  
  135.     elif o in ('-d', '--device'):
  136.         device_uri = a
  137.  
  138.     elif o in ('-l', '--logging'):
  139.         log_level = a.lower().strip()
  140.         if not log.set_level(log_level):
  141.             usage()
  142.  
  143.     elif o == '-g':
  144.         log.set_level('debug')
  145.  
  146.     elif o in ('-m', '--num', '--copies'):
  147.         try:
  148.             num_copies = int(a)
  149.         except ValueError:
  150.             log.warning("Invalid number of copies. Set to default of 1.")
  151.             num_copies = 1
  152.  
  153.         if num_copies < 1: 
  154.             log.warning("Invalid number of copies. Set to minimum of 1.")
  155.             num_copies = 1
  156.  
  157.         elif num_copies > 99: 
  158.             log.warning("Invalid number of copies. Set to maximum of 99.")
  159.             num_copies = 99
  160.  
  161.     elif o in ('-c', '--contrast'):
  162.         try:
  163.             contrast = int(a)
  164.         except ValueError:
  165.             log.warning("Invalid contrast setting. Set to default of 0.")
  166.             contrast = 0
  167.  
  168.         if contrast < -5: 
  169.             log.warning("Invalid contrast setting. Set to minimum of -5.")
  170.             contrast = -5
  171.  
  172.         elif contrast > 5: 
  173.             log.warning("Invalid contrast setting. Set to maximum of +5.")
  174.             contrast = 5
  175.  
  176.         contrast *= 25
  177.  
  178.     elif o in ('-q', '--quality'):
  179.         a = a.lower().strip()
  180.  
  181.         if a == 'fast':
  182.             quality = pml.COPIER_QUALITY_FAST
  183.  
  184.         elif a.startswith('norm'):
  185.             quality = pml.COPIER_QUALITY_NORMAL
  186.  
  187.         elif a.startswith('pres'):
  188.             quality = pml.COPIER_QUALITY_PRESENTATION
  189.  
  190.         elif a.startswith('draf'):
  191.             quality = pml.COPIER_QUALITY_DRAFT
  192.  
  193.         elif a == 'best':
  194.             quality = pml.COPIER_QUALITY_BEST
  195.  
  196.         else:
  197.             log.warning("Invalid quality. Set to default of 'normal'.")
  198.  
  199.     elif o in ('-r', '--reduction', '--enlargement'):
  200.         reduction_spec = True
  201.         try:
  202.             reduction = int(a.replace('%', ''))
  203.         except ValueError:
  204.             log.warning("Invalid reduction %. Set to default of 100%.")
  205.             reduction = 100
  206.  
  207.         if reduction < 25:
  208.             log.warning("Invalid reduction %. Set to minimum of 25%.")
  209.             reduction = 25
  210.  
  211.         elif reduction > 400:
  212.             log.warning("Invalid reduction %. Set to maximum of 400%.")
  213.             reduction = 400
  214.  
  215.     elif o in ('-f', '--fittopage', '--fit'):
  216.         fit_to_page = pml.COPIER_FIT_TO_PAGE_ENABLED
  217.  
  218.     elif o in ('-n', '--non-interactive'):
  219.         if mode_specified:
  220.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  221.             sys.exit(1)
  222.  
  223.         mode = NON_INTERACTIVE_MODE
  224.         mode_specified = True
  225.  
  226.     elif o in ('-u', '--gui'):
  227.         if mode_specified:
  228.             log.error("You may only specify a single mode as a parameter (-n or -u).")
  229.             sys.exit(1)
  230.  
  231.         mode = GUI_MODE
  232.         mode_specified = True
  233.  
  234.     elif o in ('-b', '--bus'):
  235.         bus = [x.lower().strip() for x in a.split(',')]
  236.         if not device.validateBusList(bus):
  237.             usage()
  238.  
  239.     elif o == '--lang':
  240.         if a.strip() == '?':
  241.             tui.show_languages()
  242.             sys.exit(0)
  243.  
  244.         loc = utils.validate_language(a.lower())
  245.  
  246.  
  247.  
  248. if fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED and reduction_spec:
  249.     log.warning("Fit to page specfied: Reduction/enlargement parameter ignored.")
  250.  
  251.  
  252. utils.log_title(__title__, __version__)
  253.  
  254. if os.getuid() == 0:
  255.     log.warn("hp-makecopies should not be run as root.")
  256.  
  257. # Security: Do *not* create files that other users can muck around with
  258. os.umask (0037)
  259.  
  260. if mode == GUI_MODE:
  261.     if not utils.canEnterGUIMode():
  262.         mode = NON_INTERACTIVE_MODE
  263.  
  264. if mode == GUI_MODE:
  265.     app = None
  266.     makecopiesdlg = None
  267.  
  268.     from qt import *
  269.     from ui.makecopiesform import MakeCopiesForm
  270.  
  271.     # create the main application object
  272.     app = QApplication(sys.argv)
  273.  
  274.     if loc is None:
  275.         loc = user_cfg.ui.get("loc", "system")
  276.         if loc.lower() == 'system':
  277.             loc = str(QTextCodec.locale())
  278.             log.debug("Using system locale: %s" % loc)
  279.  
  280.     if loc.lower() != 'c':
  281.         e = 'utf8'
  282.         try:
  283.             l, x = loc.split('.')
  284.             loc = '.'.join([l, e])
  285.         except ValueError:
  286.             l = loc
  287.             loc = '.'.join([loc, e])
  288.  
  289.         log.debug("Trying to load .qm file for %s locale." % loc)
  290.         trans = QTranslator(None)
  291.  
  292.         qm_file = 'hplip_%s.qm' % l
  293.         log.debug("Name of .qm file: %s" % qm_file)
  294.         loaded = trans.load(qm_file, prop.localization_dir)
  295.  
  296.         if loaded:
  297.             app.installTranslator(trans)
  298.         else:
  299.             loc = 'c'
  300.  
  301.     if loc == 'c':
  302.         log.debug("Using default 'C' locale")
  303.     else:
  304.         log.debug("Using locale: %s" % loc)
  305.         QLocale.setDefault(QLocale(loc))
  306.         prop.locale = loc
  307.         try:
  308.             locale.setlocale(locale.LC_ALL, locale.normalize(loc))
  309.         except locale.Error:
  310.             pass
  311.  
  312.     makecopiesdlg = MakeCopiesForm(bus, device_uri, printer_name, 
  313.                                    num_copies, contrast, quality, 
  314.                                    reduction, fit_to_page)
  315.  
  316.     makecopiesdlg.show()
  317.     app.setMainWidget(makecopiesdlg)
  318.  
  319.     try:
  320.         log.debug("Starting GUI loop...")
  321.         app.exec_loop()
  322.     except KeyboardInterrupt:
  323.         pass
  324.  
  325.  
  326.  
  327.  
  328.  
  329. else: # NON_INTERACTIVE_MODE
  330.     try:
  331.         if not device_uri and not printer_name:
  332.             try:
  333.                 device_uri = device.getInteractiveDeviceURI(bus, 
  334.                     filter={'copy-type': (operator.gt, 0)})
  335.  
  336.                 if device_uri is None:
  337.                     sys.exit(1)
  338.             except Error:
  339.                 log.error("Error occured during interactive mode. Exiting.")
  340.                 sys.exit(1)
  341.  
  342.         dev = copier.PMLCopyDevice(device_uri, printer_name)
  343.  
  344.         if dev.copy_type == COPY_TYPE_NONE:
  345.             log.error("Sorry, make copies functionality is not supported on this device.")
  346.             sys.exit(1)
  347.  
  348.         user_cfg.last_used.device_uri = dev.device_uri
  349.  
  350.         try:
  351.             try:
  352.                 dev.open()
  353.  
  354.                 if num_copies is None:
  355.                     result_code, num_copies = dev.getPML(pml.OID_COPIER_NUM_COPIES)
  356.  
  357.                 if contrast is None:
  358.                     result_code, contrast = dev.getPML(pml.OID_COPIER_CONTRAST)
  359.  
  360.                 if reduction is None:
  361.                     result_code, reduction = dev.getPML(pml.OID_COPIER_REDUCTION)
  362.  
  363.                 if quality is None:
  364.                     result_code, quality = dev.getPML(pml.OID_COPIER_QUALITY)
  365.  
  366.                 if fit_to_page is None and dev.copy_type == COPY_TYPE_DEVICE:
  367.                     result_code, fit_to_page = dev.getPML(pml.OID_COPIER_FIT_TO_PAGE)
  368.                 else:
  369.                     fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
  370.  
  371.                 result_code, max_reduction = dev.getPML(pml.OID_COPIER_REDUCTION_MAXIMUM)
  372.                 result_code, max_enlargement = dev.getPML(pml.OID_COPIER_ENLARGEMENT_MAXIMUM)
  373.  
  374.             except Error, e:
  375.                 log.error(e.msg)
  376.                 sys.exit(1)
  377.  
  378.             scan_style = dev.mq.get('scan-style', SCAN_STYLE_FLATBED)
  379.             log.debug(scan_style)
  380.  
  381.             if scan_style == SCAN_STYLE_SCROLLFED:
  382.                 fit_to_page = pml.COPIER_FIT_TO_PAGE_DISABLED
  383.  
  384.             log.debug("num_copies = %d" % num_copies)
  385.             log.debug("contrast= %d" % contrast)
  386.             log.debug("reduction = %d" % reduction)
  387.             log.debug("quality = %d" % quality)
  388.             log.debug("fit_to_page = %d" % fit_to_page)
  389.             log.debug("max_reduction = %d" % max_reduction)
  390.             log.debug("max_enlargement = %d" % max_enlargement)
  391.             log.debug("scan_style = %d" % scan_style)
  392.  
  393.             update_queue = Queue.Queue()
  394.             event_queue = Queue.Queue()
  395.  
  396.             dev.copy(num_copies, contrast, reduction,
  397.                      quality, fit_to_page, scan_style,
  398.                      update_queue, event_queue)
  399.  
  400.  
  401.             cont = True
  402.             while cont:
  403.                 while update_queue.qsize():
  404.                     try:
  405.                         status = update_queue.get(0)
  406.                     except Queue.Empty:
  407.                         break
  408.  
  409.                     if status == copier.STATUS_IDLE:
  410.                         log.debug("Idle")
  411.                         continue
  412.  
  413.                     elif status in (copier.STATUS_SETTING_UP, copier.STATUS_WARMING_UP):
  414.                         log.info("Warming up...")
  415.                         continue
  416.  
  417.                     elif status == copier.STATUS_ACTIVE:
  418.                         log.info("Copying...")
  419.                         continue
  420.  
  421.                     elif status in (copier.STATUS_ERROR, copier.STATUS_DONE):
  422.  
  423.                         if status == copier.STATUS_ERROR:
  424.                             log.error("Copier error!")
  425.                             dev.sendEvent(EVENT_COPY_JOB_FAIL)
  426.                             cont = False
  427.                             break
  428.  
  429.                         elif status == copier.STATUS_DONE:
  430.                             cont = False
  431.                             break
  432.  
  433.                 time.sleep(2)
  434.  
  435.         finally:
  436.             dev.close()
  437.  
  438.     except KeyboardInterrupt:
  439.         log.error("User interrupt. Canceling...")
  440.         event_queue.put(copier.COPY_CANCELED)
  441.         dev.sendEvent(EVENT_COPY_JOB_CANCELED)
  442.  
  443.     dev.waitForCopyThread()
  444.     dev.sendEvent(EVENT_END_COPY_JOB)
  445.     log.info("")
  446.     log.info("Done.")
  447.  
  448.